package com.weixing.mall.provider.auth.member.xcxAuth;

import cn.binarywang.wx.miniapp.api.WxMaService;
import cn.binarywang.wx.miniapp.bean.WxMaJscode2SessionResult;
import cn.binarywang.wx.miniapp.bean.WxMaPhoneNumberInfo;
import cn.hutool.core.util.ObjectUtil;
import com.weixing.mall.base.utils.EnumUtil;
import com.weixing.mall.base.wrapper.Result;
import com.weixing.mall.provider.api.service.MemberServiceRpc;
import com.weixing.mall.provider.enums.MsgFlagEnum;
import com.weixing.oauth2.common.userdetails.IUserAuthService;
import com.weixing.oauth2.common.userdetails.SecurityUser;
import lombok.Setter;
import me.chanjar.weixin.common.error.WxErrorException;
import org.springframework.security.authentication.AuthenticationProvider;
import org.springframework.security.authentication.DisabledException;
import org.springframework.security.authentication.InternalAuthenticationServiceException;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.crypto.password.PasswordEncoder;

/**
 * @author mall
 */
@Setter
public class MemberXcxAuthAuthenticationProvider implements AuthenticationProvider {
    private IUserAuthService userDetailService;
    private PasswordEncoder passwordEncoder;
    private WxMaService wxMaMemberService;
    private MemberServiceRpc memberServiceRpc;

    @Override
    public Authentication authenticate(Authentication authentication) {
        MemberXcxAuthAuthenticationToken authenticationToken = (MemberXcxAuthAuthenticationToken) authentication;
        // openid
        String code = (String) authenticationToken.getCode();
        String en = (String) authenticationToken.getPrincipal();
        String iv = (String) authenticationToken.getCredentials();
        String openid = null;
        String mobile = null;
        try {
            WxMaJscode2SessionResult sessionInfo = wxMaMemberService.getUserService().getSessionInfo(code);
            openid = sessionInfo.getOpenid();
            String sessionKey = sessionInfo.getSessionKey();
            WxMaPhoneNumberInfo wxMaPhoneNumberInfo = wxMaMemberService.getUserService().getPhoneNoInfo(sessionKey,en, iv);
            if (ObjectUtil.isEmpty(wxMaPhoneNumberInfo) || ObjectUtil.isEmpty(wxMaPhoneNumberInfo.getPhoneNumber())) {
                throw new InternalAuthenticationServiceException("获取手机号授权失败");
            }
             mobile = wxMaPhoneNumberInfo.getPurePhoneNumber();
            // 处理H5绑定逻辑
        } catch (WxErrorException e) {
            throw new InternalAuthenticationServiceException("code 换取openid失败");
        }
        SecurityUser user = userDetailService.loadUserByXcxOpenId(openid);
        String msgFlag = user.getMsgFlag();
        MsgFlagEnum iEnum = EnumUtil.getIEnum(MsgFlagEnum.class, msgFlag);
        // 如果openid存在则直接返回
        if (MsgFlagEnum.SUCCESS.equals(iEnum)){
            if (!user.isEnabled()){
                throw new DisabledException("该账户已禁用");
            }
            MemberXcxAuthAuthenticationToken authenticationResult = new MemberXcxAuthAuthenticationToken(user, user.getAuthorities());
            authenticationResult.setDetails(authenticationToken.getDetails());
            return authenticationResult;
        }else if (MsgFlagEnum.EXCEPTION.equals(iEnum)){
            throw new InternalAuthenticationServiceException(iEnum.getDesp());
        }

        SecurityUser userMobile = userDetailService.loadUserByUsername(mobile);
        MsgFlagEnum flagEnum = EnumUtil.getIEnum(MsgFlagEnum.class, userMobile.getMsgFlag());
        if (MsgFlagEnum.SUCCESS.equals(flagEnum)){
            if (!user.isEnabled()){
                throw new DisabledException("该账户已禁用");
            }
            //  执行关联逻辑
            memberServiceRpc.updateXcxOpenId(openid,mobile);
            MemberXcxAuthAuthenticationToken authenticationResult = new MemberXcxAuthAuthenticationToken(userMobile, userMobile.getAuthorities());
            authenticationResult.setDetails(authenticationToken.getDetails());
            return authenticationResult;
        }else if (MsgFlagEnum.EXCEPTION.equals(flagEnum)){
            throw new InternalAuthenticationServiceException(iEnum.getDesp());
        }

        // 注册用户
        Result result = memberServiceRpc.xcxRegister(openid,mobile);
        // 注册后重新登录
        SecurityUser securityUser = userDetailService.loadUserByUsername(mobile);
        MsgFlagEnum msgFlagEnum = EnumUtil.getIEnum(MsgFlagEnum.class, securityUser.getMsgFlag());
        if (MsgFlagEnum.SUCCESS.equals(msgFlagEnum)){
            if (!securityUser.isEnabled()){
                throw new DisabledException("该账户已禁用");
            }

        }else if (MsgFlagEnum.EXCEPTION.equals(msgFlagEnum)){
            throw new InternalAuthenticationServiceException(iEnum.getDesp());
        }

        MemberXcxAuthAuthenticationToken authenticationResult = new MemberXcxAuthAuthenticationToken(securityUser, securityUser.getAuthorities());
        authenticationResult.setDetails(authenticationToken.getDetails());
        return authenticationResult;
    }

    @Override
    public boolean supports(Class<?> authentication) {
        return MemberXcxAuthAuthenticationToken.class.isAssignableFrom(authentication);
    }
}
